package com.demo.webapp.views.freemarker.directive.config;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;

import org.apache.commons.digester3.Digester;
import org.apache.commons.digester3.binder.DigesterLoader;
import org.apache.commons.digester3.xmlrules.FromXmlRulesModule;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.demo.common.ClassLoaderUtils;
import com.demo.webapp.views.freemarker.directive.model.DirectiveGroupModel;

/**
 * 自定义指令的配置管理器
 * 该管理器从配置文件中读取自定义指令信息
 * 封装到对象模型中
 * @author ryuu.kk
 *
 */
public class ConfigurationManager {
	
	protected static final Log LOG = LogFactory.getLog(ConfigurationManager.class);
	
	private static ConfigurationManager instance;
	private static final String CONFIGURATION_FILE_NAME = "classpath:com/demo/webapp/views/freemarker/directive/config/demo-config.xml";
	private static final String CONFIGURATION_RULE_FILE = "classpath:com/demo/webapp/views/freemarker/directive/config/digester-rule.xml";
	
	protected List<DirectiveGroupModel> directiveGroupModelList;
	private ClassLoader classLoader;
	private String configFile = CONFIGURATION_FILE_NAME;
	
	// 全局配置,由于不是final对象并且是普通list,则有修改的可能,这里该对象应该只读。(以后修正...)
	// public static List<DirectiveGroupModel> Global_Driective_Model;
	
	/**
	 * 简单的单例模式
	 * @param file 文件位置
	 * @param loader ClassLoader
	 * @return ConfigurationManager
	 */
	public static ConfigurationManager getInstance(String file, ClassLoader loader) {
		if (instance == null) {
			instance = new ConfigurationManager(file, loader);
			instance.load();
		};
		return instance;
	}
	
	/**
	 * 简单的单例模式
	 * @return ConfigurationManager
	 */
	public static ConfigurationManager getInstance() {
		if (instance == null) {
			instance = new ConfigurationManager();
			instance.load();
		};
		return instance;
	}
	
	private ConfigurationManager() {
		// 构造函数
		this.classLoader = Thread.currentThread().getContextClassLoader();
	}
	
	private ConfigurationManager(String file) {
		// 构造函数
		this.configFile = file;
		this.classLoader = Thread.currentThread().getContextClassLoader();
	}
	
	private ConfigurationManager(String file, ClassLoader loader) {
		// 构造函数
		this.configFile = file;
		this.classLoader = loader;
	}
	
	public ClassLoader getClassLoader() {
		return classLoader;
	}


	public void load() {
		init();
	}

	public void destroy() {}
	
	protected void init() {
		
		// 已读取自定义指令模型列表
		if (directiveGroupModelList != null) {
			return;
		}
		//初始化配置对象
		directiveGroupModelList = new ArrayList<DirectiveGroupModel>();
		
		DigesterLoader loader = DigesterLoader.newLoader(new FromXmlRulesModule() {
					@Override
					protected void loadRules() {
						try {
							loadXMLRules(ClassLoaderUtils.getResourceAsStream(CONFIGURATION_RULE_FILE, this.getClass()));
						} catch (FileNotFoundException e) {
							e.printStackTrace();
						}
					}
				});
		loader.setClassLoader(this.classLoader != null ? this.classLoader
				: Thread.currentThread().getContextClassLoader());
		Digester digester = loader.newDigester();
		InputStream input = null;

		try {
			// 读取资源
			input = ClassLoaderUtils.getResourceAsStream(configFile, this.getClass());

			// 设置栈顶对象
			digester.push(this);
			digester.parse(input);
			
			//ConfigurationManager.Global_Driective_Model = this.getDirectiveGroupModelList();
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			if (input != null) {
				try {
					input.close();
				} catch (IOException e) {
				}
			}
		}
	}

	public void addTaglib(DirectiveGroupModel model) {
		directiveGroupModelList.add(model);
	}
	
	public List<DirectiveGroupModel> getDirectiveGroupModelList() {
		return directiveGroupModelList;
	}

	public void setConfigFile(String configFile) {
		this.configFile = configFile;
	}

	public static void main(String[] args) {
		ConfigurationManager manager = new ConfigurationManager();
		manager.load();
	}
}
